package com.cee.quartz.job.http;

import com.cee.http.HttpResult;
import com.cee.http.HttpUtils;
import com.cee.quartz.job.JobType;
import com.cee.quartz.job.base.BaseQuartzJob;
import com.cee.sch.job.dto.ScheduleJobDTO;
import com.cee.sch.job.dto.ScheduleJobLogDTO;
import com.cee.sch.job.enumeration.JobExecutionStatus;
import com.cee.sch.job.service.ScheduleJobLogService;
import com.cee.sch.job.service.ScheduleJobService;

import com.cee.util.JsonUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.quartz.JobDetail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * HttpQuartzJob is a dedicated quartz job that calls through http by HttpJobDataDTO configured in jobDetail with key 'HTTP_JOB_DATA_KEY'.
 * The job calls remote http API asynchronously.
 *
 * @author Parko
 */
@Component
public class HttpQuartzJob extends BaseQuartzJob {

    public static final String HTTP_JOB_DATA_KEY = "HTTP_JOB_DATA_KEY";
    public static final String POST_METHOD = "POST";
    public static final String CALL_JOB_EXCEPTION_CODE = "9";


    @Autowired
    private ScheduleJobService scheduleJobService;

    @Autowired
    private ScheduleJobLogService scheduleJobLogService;

    @Value("${system.jobLogCallbackUrl}")
    private String jobLogCallbackUrl;

    @Override
    protected void executeJob(JobDetail jobDetail, ScheduleJobLogDTO jobLog) throws Exception {
        HttpJobDataDTO jobData = JsonUtil.parse((String) jobDetail.getJobDataMap().get(HTTP_JOB_DATA_KEY), HttpJobDataDTO.class);
        logger.info("jobData: {}", JsonUtil.format(jobData));


        if (!StringUtils.equalsIgnoreCase(jobData.getMethod(), POST_METHOD)) {
            throw new IllegalStateException("Only accept 'POST' method, but the method is '" + jobData.getMethod() + "' now");
        }

        ScheduleJobDTO scheduleJob = scheduleJobService.getScheduleJobByNameAndGroup(jobDetail.getKey().getName(), jobDetail.getKey().getGroup());
        Map<String, Object> map = new HashMap<>();
        map.put("username", jobData.getUsername());
        map.put("password", jobData.getPassword());
        map.put("jobLogCallbackUrl", jobLogCallbackUrl);
        //setToken(jobDetail, map);

        map.put("jobId", scheduleJob.getVisSysSchJobKey());
        if (jobData.getRequestBody() != null) {
            for (Map.Entry<String, Object> entry : jobData.getRequestBody().entrySet()) {
                map.put(entry.getKey(), entry.getValue());
            }
        }

        String url = jobData.getUrl();
        logger.info("url: {}", url);

        // create job log for the remote side which executing the task then to make http request to update the job log asynchronously.

        map.put("jobLogId", jobLog.getVisSysSchJobLogKey());

        logger.info("map: {}", JsonUtil.format(map));

        HttpResult result = HttpUtils.doPost(url, map, null);
        int code = result.getCode();
        logger.info("result.getCode(): {}", code);

        // if the status code is not 200, then add job log, otherwise
        if (HttpStatus.SC_OK != code) {
            // update schedule job log as 'FAILED' JobExectionStatus
            jobLog.setStatus(JobExecutionStatus.FAILED.getCode());
            jobLog.setErrorCode(String.valueOf(code));
            jobLog.setErrorMsg("HttpStatus is " + code);
            jobLog.setEndTime(new Date());

            scheduleJobLogService.updateScheduleJobLog(jobLog);
        }
    }


    @Override
    protected JobType getJobType() {
        return JobType.HTTP;
    }


}

